﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;



namespace FactoryInstaller {

    public partial class DataBaseCreationForm : Form {

        const string DB_NAME = "Factory_v1a";

        System.Data.IDbConnection conection;
        System.Data.IDbTransaction trans;

        public bool wasCanceled = true;

        string sqlScriptPath;
        string factoryOwnerAccount;


        private bool useWindowsAuthentication = false;

        string dbname = DB_NAME;

        public DataBaseCreationForm(string sqlScriptPath, bool useWindowsAuthentication) {
            InitializeComponent();
            this.sqlScriptPath = sqlScriptPath;
            wasCanceled = true;

            this.useWindowsAuthentication = useWindowsAuthentication;
            if(!useWindowsAuthentication)
                this.accessKey = Guid.NewGuid().ToString();
            
            this.factoryOwnerAccount = System.Environment.GetEnvironmentVariable("USERDOMAIN") + "\\" + System.Environment.GetEnvironmentVariable("USERNAME");
            
            //factoryOwnerAccount = Environment.UserDomainName + "\\" + Environment.UserName;            
           
        }
                
        private void CreateDatabase() {
            try {
                System.Data.IDbCommand cmd = new System.Data.SqlClient.SqlCommand("CREATE DATABASE [" + dbname + "] COLLATE Latin1_General_CI_AS; EXEC dbo.sp_dbcmptlevel @dbname=N'" + dbname + "', @new_cmptlevel=90");
                cmd.Connection = conection;
                cmd.ExecuteNonQuery();
            } catch (Exception ex) {
                throw new System.Configuration.Install.InstallException("Sorry, could not create The Scrum Factory database.\n\n" + ex.Message);
            }
        }

        public void DropDatabase() {
            try {
                System.Data.IDbCommand cmd = new System.Data.SqlClient.SqlCommand("DROP DATABASE [" + dbname + "]");
                cmd.Connection = conection;
                cmd.Transaction = null;
                cmd.ExecuteNonQuery();
            }
            catch (Exception) {
                throw new System.Configuration.Install.InstallException("Sorry, could not drop The Scrum Factory database.");
            }
        }

        private void button1_Click(object sender, EventArgs e) {

            conection = new System.Data.SqlClient.SqlConnection(ConnectionStringForDBCreation);
            try {
                conection.Open();
            } catch (Exception) {
                MessageBox.Show("Could not connect to the database. Please verify the database address and credentials.", "Could not connect to the database");
                return;
            }

            // gets the database name            
            dbname = GetDatabaseName();
            
            
            // create database
            CreateDatabase();

            trans = conection.BeginTransaction();

            try {

                // create view, tabes etc..
                string script = GetSQLScript("factory.sql");
                RunScript(script);
                trans.Commit();

            } catch (Exception ex) {
                trans.Rollback();                
                MessageBox.Show(ex.Message);
                DropDatabase();
                throw new System.Configuration.Install.InstallException("Sorry, could not create The Scrum Factory tables.");
            }
                        
            if (conection.State != ConnectionState.Closed)
                conection.Close();


            wasCanceled = false;
            Close();
        }
        string password = null;
        private string GeneratedUserPassword {
            get {
                if (password != null)
                    return password;
                string con = "ABCFG48opOPTRE$%&*JKMAWEYlllw892761ght132opyTRWCk";
                password = "";                
                Random r = new Random();
                
                for(int i=0; i<=5; i++)
                    password = password + con[r.Next(con.Length-1)];
                return password;
            }
        }

        private string GetSQLScript(string file) {
            string script;            
            System.IO.StreamReader fs = new System.IO.StreamReader(sqlScriptPath + "\\" + file);
            script = fs.ReadToEnd();
            fs.Close();
            return script;
        }

        private void windowsAuthenticationCheckBox_CheckedChanged(object sender, EventArgs e) {
            if (!windowsAuthenticationCheckBox.Checked)
                groupBox1.Visible = true;
            else
                groupBox1.Visible = false;
        }

        

        private string ConnectionStringForDBCreation {
            get {
                System.Data.SqlClient.SqlConnectionStringBuilder s = new System.Data.SqlClient.SqlConnectionStringBuilder();
                s.DataSource = serverAddressTextBox.Text;                
                s.IntegratedSecurity = windowsAuthenticationCheckBox.Checked;
                s.InitialCatalog = "master";
                if (!windowsAuthenticationCheckBox.Checked) {
                    s.UserID = userTextBox.Text;
                    s.Password = passwordTextBox.Text;
                }
                return s.ConnectionString;
            }
        }

        public string ConnectionStringForApplication {
            get {
                System.Data.SqlClient.SqlConnectionStringBuilder s = new System.Data.SqlClient.SqlConnectionStringBuilder();
                s.DataSource = serverAddressTextBox.Text;                
                s.InitialCatalog = dbname;
                s.UserID = dbname+"_Login";
                s.Password = GeneratedUserPassword;                
                return s.ConnectionString;
            }
        }

        private string GetDatabaseName() {
            
                string dbname = DB_NAME;
                try {
                    bool exists = true;
                    int i = 1;
                    while (exists) {
                        System.Data.IDbCommand cmd = new System.Data.SqlClient.SqlCommand("SELECT db_id('" + dbname + "')");
                        cmd.Connection = conection;
                        cmd.Transaction = trans;
                        object o = cmd.ExecuteScalar();
                        if (o == null || o == DBNull.Value)
                            exists = false;
                        else {
                            dbname = DB_NAME + "_" + i;
                            i++;
                        }
                    }
                } catch (Exception) {
                    throw new System.Configuration.Install.InstallException("Sorry, could not find database name.");
                }
                return dbname;            
        }
        public string accessKey = null;

        private void RunScript(string sqlScript) {

            sqlScript = sqlScript.Replace("$DB_NAME$", dbname);
            sqlScript = sqlScript.Replace("$USER_PASSWORD$", GeneratedUserPassword);

            if (useWindowsAuthentication) {
                sqlScript = sqlScript.Replace("$FACTORY_OWNER_USER$", factoryOwnerAccount);
                sqlScript = sqlScript.Replace("$ACCESS_KEY$", "NULL");
            } else {
                sqlScript = sqlScript.Replace("$FACTORY_OWNER_USER$", "FACTORY\\admin");
                sqlScript = sqlScript.Replace("$ACCESS_KEY$", "'" + accessKey + "'");
            }
            
            
            


            string[] delimitedSqlCommand = sqlScript.Split(new string[1] { "GO;" }, StringSplitOptions.RemoveEmptyEntries);
            

            
            // Creates the db objects
            foreach (string sqlLine in delimitedSqlCommand) {
                if(!String.IsNullOrEmpty(sqlLine)) {
                    System.Data.IDbCommand cmd = new System.Data.SqlClient.SqlCommand(sqlLine);
                    cmd.Connection = conection;
                    cmd.Transaction = trans;
                    cmd.ExecuteNonQuery();                    
                }
            
            }
                        
        }

        private void button1_Click_1(object sender, EventArgs e) {
            Close();
        }
    }
}
